﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using OauthProvider;
using System.IO;

namespace Chat_WebServer.Controllers
{
    public class OAuthController : ApiController
    {
        const String Author_url = "http://localhost:53220/Authorization/GetAuthor";
        private static IOAuthProvider provider;

        public OAuthController()
        {
            var consumerStore = new ConsumerStore();
            SimpleTokenStore tokenStore = new SimpleTokenStore();
            provider = new OAuthProvider(tokenStore,
                                   new ConsumerValidationInspector(consumerStore),
                                   new OAuth10AInspector(tokenStore));
        }

        public HttpResponseMessage GetRequestToken()
        {
            IOAuthContext context = new OAuthContextBuilder().FromUri(HttpMethod.Get.ToString(), Request.RequestUri);
            IToken rqtoken = provider.GrantRequestToken(context);
            String content = rqtoken.ToString();
            content += "&" + Parameters.OAuth_Url_Author + "=" + UriUtility.UrlEncode(Author_url);
            content = content.Replace("\\", "");
            var response = Request.CreateResponse(HttpStatusCode.OK, content);
            return response;
        }

        public String GetApprovalRequestToken([FromUri]bool isApproved, [FromUri]String userName)
        {
            IOAuthContext context = new OAuthContextBuilder().FromUri(HttpMethod.Get.ToString(), Request.RequestUri);
            String tokenString = String.Empty;
            if (context.Token != null) tokenString = context.Token;
            else return String.Empty;
            if (string.IsNullOrEmpty(tokenString)) return "The token string in the parameters collection was invalid/missing";

            if (isApproved)
                return ApprovalRequestToken(tokenString, userName);
            else
                return DenyRequestToken(tokenString, userName);
        }

        public HttpResponseMessage GetExchangeRequestToken(String id)
        {
            IOAuthContext context = new OAuthContextBuilder().FromUri(HttpMethod.Get.ToString(), Request.RequestUri);

            IToken accessToken = provider.ExchangeRequestTokenForAccessToken(context);
            String content = accessToken.ToString() + "&" + Parameters.OAuth_Expire + "=" + ((MiniAccessToken)accessToken).ExpireyDate.ToString();
            var response = Request.CreateResponse(HttpStatusCode.OK, content);
            return response;
        }


        public HttpResponseMessage RefreshToken()
        {
            IOAuthContext context = new OAuthContextBuilder().FromUri(HttpMethod.Get.ToString(), Request.RequestUri);

            bool sc = provider.RefreshAccessToken(context);
            if (sc)
                return Request.CreateResponse(HttpStatusCode.OK);
            else return Request.CreateResponse(HttpStatusCode.Unauthorized);
        }


        private String CreateResponse(String tokenString, bool granted)
        {
            MiniRequestToken requestToken = (MiniRequestToken)TokenUtility.GetToken(tokenString, TokenType.Request);

            string callBackUrl = requestToken.CallbackUrl;
            string verifier = requestToken.Verifier;

            if (!string.IsNullOrEmpty(callBackUrl))
            {
                if (!callBackUrl.Contains("?")) callBackUrl += "?";
                else callBackUrl += "&";

                callBackUrl += Parameters.OAuth_Token + "=" + UriUtility.UrlEncode(tokenString);
                callBackUrl += "&" + Parameters.OAuth_Verifier + "=" + UriUtility.UrlEncode(verifier);

                return callBackUrl;
            }
            else
            {
                if (granted)
                {
                    /* string successMessage = string.Format(
                       "You have been successfully granted Access, To complete the process, please provide <I>{0}</I> with this verification code: <B>{1}</B>",
                       requestToken.ConsumerKey, HttpUtility.HtmlEncode(requestToken.Verifier));
                     */
                    return "Success";
                }
                else
                {
                    return "Denied";
                }
            }
        }

        private String DenyRequestToken(String tokenString, String userName)
        {
            MiniRequestToken requestToken = (MiniRequestToken)TokenUtility.GetToken(tokenString, TokenType.Request);

            requestToken.Verifier = UnguessableGenerator.GenerateUnguessable();

            requestToken.AccessDenied = true;

            requestToken.SaveToken();
            return CreateResponse(tokenString, false);
        }

        private String ApprovalRequestToken(String tokenString, String userName)
        {
            MiniRequestToken requestToken = (MiniRequestToken)TokenUtility.GetToken(tokenString, TokenType.Request);

            using (var db = new AccountEntities())
            {
                AccessToken acc = db.AccessTokens.FirstOrDefault(t => t.UserName == userName);
                if (acc != null)
                    TokenUtility.RemoveToken(acc.Token);
            }
            var accessToken = new MiniAccessToken
            {
                ConsumerKey = requestToken.ConsumerKey,
                Realm = requestToken.Realm,
                Token = Guid.NewGuid().ToString(),
                TokenSecret = Guid.NewGuid().ToString(),
                UserName = userName,
                ExpireyDate = DateTime.Now.AddHours(1)
            };

            accessToken.SaveToken();

            requestToken.AccessToken = accessToken;

            requestToken.Verifier = UnguessableGenerator.GenerateUnguessable();

            requestToken.SaveToken();
            return CreateResponse(tokenString, true);
        }
    }
}
